/*
	Simple Software Renderer (SSRenderer)
	Copyright (C) 2007 Piotr Orzechowski <piotr.orzechowski@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <cassert>
#include "./ErrorStack.h"

namespace util
{

void ErrorStack::_Deinitialize()
{
	m_pErrorStrings = NULL;
	while(!IsEmpty())
	{
		m_ErrorStack.pop();
		m_InfoStack.pop();
	}
	m_OutputStreams.clear();
}

void ErrorStack::AddOutputStream(std::ostream &stream)
{
	m_OutputStreams.push_back(&stream);
}

void ErrorStack::SetErrorStrings(const char* pErrorStrings[], int count)
{
	if (pErrorStrings != NULL && count > 0)
	{
		m_pErrorStrings = pErrorStrings;
		m_StringsCount = count;
	}
}

const char* ErrorStack::ErrorToString(int errorId) const
{
	if (m_pErrorStrings != NULL && errorId >= 0 && errorId < m_StringsCount)
	{
		return m_pErrorStrings[errorId];
	}
	else
	{
		return NULL;
	}
}

int ErrorStack::Pop(const char* &pInfo)
{
	int top;

	if (!IsEmpty())
	{
		top = m_ErrorStack.top();
		m_ErrorStack.pop();

		pInfo = m_InfoStack.top();
		m_InfoStack.pop();
	}
	else
	{
		// Stack is empty
		top = -1;
		pInfo = NULL;
	}

	return top;
}


void ErrorStack::Push(const char* pInfo, int errorCode)
{
	assert(errorCode >= 0 && "Error code must be >= 0");

	m_ErrorStack.push(errorCode);
	m_InfoStack.push(pInfo);

	_FlushStreams();
}

bool ErrorStack::IsEmpty() const
{
	return m_ErrorStack.empty();
}

void ErrorStack::_FlushStreams()
{
	// Go through all output streams and log the message
	int id;
	const char* info;

	if (!IsEmpty())
	{
		id = m_ErrorStack.top();
		info = m_InfoStack.top();

		for(unsigned int i = 0; i < m_OutputStreams.size(); ++i)
		{
			(*m_OutputStreams[i]) << "[" << id << "] : ";

			if (ErrorToString(id) != NULL)
			{
				(*m_OutputStreams[i]) << ErrorToString(id);
			}

			if (info != NULL)
			{
				(*m_OutputStreams[i]) << "\n>> " << info;
			}

			(*m_OutputStreams[i]) << std::endl;
		}
	}
}

} // namespace

